Once you've decided how to handle sides in your game, you can move on to the initial unit setup. Initial unit setup is very important, since it has a major bearing on how the rest of the game will go, and can be done in a number of different ways.
GDL allows you to define everything about every starting unit in the game. This is a powerful approach, but requires much preparation. An advantage of predefined units is that there are no unpleasant surprises. For instance, suppose you designed an empire game with ships and cities, but a random setup leaves some players entirely landlocked. Not only will those players be very unhappy, they might come looking for you before they've calmed down!
Asking for initial units is pretty easy, you can either type them into a file or create them directly, using the appropriate designer tool in a game.
(city) (city 11 12 1) (city (n "Brigadoon")) (city (@ 10 10) (n "New York")) (city (@ 20 10) (n "London") (hp 22))
The only info that you absolutely have to supply is the unit's type. If the position is missing, the unit will be placed at a random location. If the side number/name is missing, the unit will be independent or on the first possible side.
While the type, position, and side of units is important, exact values of the
other properties are rarely important for a scenario. Also, a unit with
fewer filled-in properties can be used in different games.
For instance, a list of the present-day major cities worldwide
really needs only name and location for each;
the game design can fill in everything else.
One way to do this would be to set up an appropriate
unit-defaults
just before including the module.
To make units start inside transports, you need to specify the t#
property for the occupant, and have its value be the id number or name
of some other unit. Your players may get an error message if the
occupant is not of an allowed type for the transport to hold.
Despite the advantages of predefining initial units,
this doesn't help when you want variable groups of units
to appear in a randomly-generated world.
Instead, you should use the make-countries
synthesis method.
The basic idea is that the method picks a good location for each side's
country, scatters an initial set of units around that location,
then possibly grows the country outwards.
You can do anything from small widely-separated countries to an
interlocking nightmare resembling pre-Bismarck Germany.
Because of this, and because of the requirement that this
method generate random setups that are as fair as possible,
you have a great many parameters to work with.
These parameters should be tuned carefully - you will probably
need to generate and study lots of initial setups, especially
if your parameters constrain the countries very tightly; the method
cannot backtrack to fix a poor combination of placements.
The first step in country generation is to select a location for
each side's country. The location is a point that is the "center"
of the country (the exact value will be unimportant to players,
and is not used outside this method). The constraints are that the
center of each country is farther than country-separation-min
from the center of every other country, that the center is within
country-separation-max
of at least one other country, and that the
given initial area of the country (as defined by country-radius-min
)
includes numbers of cells of each terrain type bounded by
country-terrain-min
and country-terrain-max
.
The reason for the separation constraints is that having countries too close together or too far apart can create serious problems. Consider the poor soul who gets tightly sandwiched between two enemies, thus becoming lunchmeat, ha ha, or the not-quite-so-poor-but-still-unlucky player who ends up on the wrong side of a very large world. (Keep in mind that your players may ask for a much larger world than you were thinking of when you designed the game.)
The terrain constraints help you put the country in a reasonable mix of terrain. For instance, if you want to ensure that your countries include some land, but be on the coast rather than inland, then you should say that the country must have a minimum of 1 sea cell and 1 land cell. (In practice, the values should be higher, so you don't get small islands being used as entire countries and lakes being considered the ocean.) Keep in mind that these constraints may be impossible to satisfy, for instance if a particular world does not have enough of the sort of terrain that is being required in a country. If the basic placement constraints fail, Xconq will just pick a random location, warn about it, and then leave it up to the players to decide on whether to play the game "as it lies".
;;; Keep countries close together, but not too close. (set country-separation-min 20) (set country-separation-max 25)
Once Xconq has decided on locations for each country, it then places
the initial stock of units. You define this initial stock via the
unit properties start-with
and independent-near-start
.
The start-with
units start out belonging to the side, while the
independent-near-start
units are independent. The locations
of these units are random within country-radius-min
of the
center, but are weighted according to the table favored-terrain
.
This table is very important; it is the percent chance that a unit of a given
type will be placed in terrain of the given type. 100 is guaranteed to work,
and 0 is an absolute prohibition. Since make-countries
tries repeatedly to place each start-with
unit until it succeeds,
then even terrain with a favored-terrain
value of only 10% will get used
if there is no other choice, so the table affects the distribution of units
rather than the number that get placed. If a starting unit cannot
be placed on any available terrain, but can be an occupant,
then Xconq will attempt to put it inside
some unit already present. This is a good way to begin a game with
aircraft at airports rather than in the air.
The upshot is that all this
will do a reasonable layout if the parameters are set reasonably.
If, however, favored-terrain
is never > 0 for the start-with
units and the country terrain,
but there is some other terrain type for which this would work,
Xconq will change the terrain.
If even that doesn't work, the method will fail [or just complain?].
This example is from the standard Xconq game:
(set country-radius-min 3) (add city start-with 1) (add town independent-near-start 5) (table favored-terrain 0 ((town city) plains 100) (town (desert forest mountains) (20 30 20)) )
The net effect is to give each player one city outright and 5 towns nearby.
Although created independent, these towns can be easily taken over right at the
beginning of a game, so they are a kind of "warmup" (like the
pushing of pawns at the beginning of a chess game). The favored-terrain
table allows cities to appear only in plains, while giving more options to
towns, since they can appear in deserts, forests, and mountains. Even so,
towns are 5 times more likely to be in plains, which is reasonable.
The optional last step in country generation is to grow the countries outwards from the initial area. This is basically a simple simulation of the historical forces that give countries their variety of shapes. The algorithm works by deciding whether to add to the country each cell at each distance from the country's center. The chance depends on the terrain type and whether the cell has already been given to another country. Once a cell has been given to the country, then the method decides whether to add a sided or independent unit to the cell, or whether to change the side of an existing unit. Country growth stops when either the absolute maximum radius has been reached, or too few cells have been added to the country, whichever comes first.
This example is from one of the variants of the standard game:
(game-module "standard" ... (variants ... ("Large Countries" eval (set country-radius-max 100) ) ))
The resulting effect is to make all the countries border on each directly.